Notas clase 3: Introducción a Tidyverse
Curso: Metodología Cuantitativa.
Magíster en Trabajo Social, Pontificia Universidad Católica de Chile.
Introducción
En este documento se profundizará en las funciones disponibles en tidyverse para el procesamiento, limpieza y análisis de datos. En particular, aquellas provenientes del paquete dplyr.
Para esta sesión trabajaremos con un conjunto de datos más lúdico. En concreto, aquellos disponibles en el paquete pokemon. Este contiene información para 949 filas, que corresponden a los pokémon que han salido en cada generación del famoso videojuego de Nintendo y 22 columnas, que incluyen atributos para cada uno de ellos.
Todas los códigos utilizarán el nuevo pipe de R |>, disponible desde R 4.1.0.
1 glimpse()
Permite obtener una vista rápida de la estructura del conjunto de datos, mostrando información como:
- Número de filas y columnas.
- Nombre y tipo de dato para las variables.
- Algunos datos de ejemplo.
Se recomienda usar esta función cuando se inicia el trabajo con un conjunto de datos, para conocer cuál es la información disponible. También se sugiere revisar la estructura de la base de datos en la medida que se realizan modificaciones. Por ejemplo:
- Cuando se agregan o eliminan columnas.
- Cuando se modifican columnas cambiando su tipo de dato.
- Variables renombradas, etc.
Rows: 949
Columns: 22
$ id <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,…
$ pokemon <chr> "bulbasaur", "ivysaur", "venusaur", "charmander", "cha…
$ species_id <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,…
$ height <dbl> 0.7, 1.0, 2.0, 0.6, 1.1, 1.7, 0.5, 1.0, 1.6, 0.3, 0.7,…
$ weight <dbl> 6.9, 13.0, 100.0, 8.5, 19.0, 90.5, 9.0, 22.5, 85.5, 2.…
$ base_experience <dbl> 64, 142, 236, 62, 142, 240, 63, 142, 239, 39, 72, 178,…
$ type_1 <chr> "grass", "grass", "grass", "fire", "fire", "fire", "wa…
$ type_2 <chr> "poison", "poison", "poison", NA, NA, "flying", NA, NA…
$ hp <dbl> 45, 60, 80, 39, 58, 78, 44, 59, 79, 45, 50, 60, 40, 45…
$ attack <dbl> 49, 62, 82, 52, 64, 84, 48, 63, 83, 30, 20, 45, 35, 25…
$ defense <dbl> 49, 63, 83, 43, 58, 78, 65, 80, 100, 35, 55, 50, 30, 5…
$ special_attack <dbl> 65, 80, 100, 60, 80, 109, 50, 65, 85, 20, 25, 90, 20, …
$ special_defense <dbl> 65, 80, 100, 50, 65, 85, 64, 80, 105, 20, 25, 80, 20, …
$ speed <dbl> 45, 60, 80, 65, 80, 100, 43, 58, 78, 45, 30, 70, 50, 3…
$ color_1 <chr> "#78C850", "#78C850", "#78C850", "#F08030", "#F08030",…
$ color_2 <chr> "#A040A0", "#A040A0", "#A040A0", NA, NA, "#A890F0", NA…
$ color_f <chr> "#81A763", "#81A763", "#81A763", NA, NA, "#DE835E", NA…
$ egg_group_1 <chr> "monster", "monster", "monster", "monster", "monster",…
$ egg_group_2 <chr> "plant", "plant", "plant", "dragon", "dragon", "dragon…
$ url_icon <chr> "//archives.bulbagarden.net/media/upload/7/7b/001MS6.p…
$ generation_id <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ url_image <chr> "https://raw.githubusercontent.com/HybridShivam/Pokemo…
A continuación se detallan algunos campos relevantes con los que trabajaremos:
| Columna | Descripción |
|---|---|
| id | Identificador numérico de cada pokémon |
| pokemon | Identificador de cada pokémon con su nombre |
| height | Altura del pokémon |
| weight | Peso del pokémon |
| base_experience | Experiencia base numérica del pokémon |
| type_1 | Tipo primario de cada pokémon |
| type_2 | Tipo secundario de cada pokémon |
| hp | Valor numérico que representa la vida de cada pokémon |
| attack | Valor numérico que representa el ataque de cada pokémon |
| defense | Vector numérico que representa la defensa de cada pokémon |
| special_defense | Vector numérico que representa la defensa especial de cada pokémon |
| speed | Vector numérico que representa la velocidad de cada pokémon |
| color_1 | Color primario de cada pokémon |
| color_2 | Color secundario de cada pokémon |
| generation_id | Valor que representa la generación de cada pokémon |
2 select()
Se utiliza para seleccionar columnas de un conjunto de datos. Este procedimiento puede agruparse en dos grandes tipos:
- Selección positiva: indicar las variables que se desea incluir.
- Selección negativa: indicar las variables que no se desea incluir.
La forma en que se realice la selección dependerá principalmente de las preferencias de cada analista, del tamaño del conjunto de datos y si las variables -o grupos de ellas- comparten algún patrón en sus sus nombres.
Independiente del tipo de selección, se pueden usar los siguientes métodos:
- Especificando las variables a seleccionar por nombre y/o posición.
- Utilizar otras funciones como
selection helpers. - Por un grupo de variables indicadas en un vector.
- Usando
where(), que aplicará una función a todas las variables y retornará aquellas conTRUE. Este método permite, entre otras opciones, seleccionar por tipo de dato.
2.1 Por nombre y/o posición
En este caso, la selección de columnas se realiza indicando el nombre o posición de las columnas.
- Si se especifican los nombres, estos deben estar escritos tal y como aparecen en el conjunto de datos, respetando mayúsculas y minúsculas. Para evitar problemas en el trabajo con los datos se recomienda fuertemente tener estandarizados los nombres de variables.
- Usualmente es más recomendable emplear nombres.
- La función
select()retornará el tibble con las variables indicadas, en el mismo orden en el que se especificó la selección.
# A tibble: 949 × 1
pokemon
<chr>
1 bulbasaur
2 ivysaur
3 venusaur
4 charmander
5 charmeleon
6 charizard
7 squirtle
8 wartortle
9 blastoise
10 caterpie
# ℹ 939 more rows
# A tibble: 949 × 1
pokemon
<chr>
1 bulbasaur
2 ivysaur
3 venusaur
4 charmander
5 charmeleon
6 charizard
7 squirtle
8 wartortle
9 blastoise
10 caterpie
# ℹ 939 more rows
# A tibble: 949 × 4
pokemon species_id base_experience type_1
<chr> <dbl> <dbl> <chr>
1 bulbasaur 1 64 grass
2 ivysaur 2 142 grass
3 venusaur 3 236 grass
4 charmander 4 62 fire
5 charmeleon 5 142 fire
6 charizard 6 240 fire
7 squirtle 7 63 water
8 wartortle 8 142 water
9 blastoise 9 239 water
10 caterpie 10 39 bug
# ℹ 939 more rows
# A tibble: 949 × 4
pokemon species_id base_experience type_1
<chr> <dbl> <dbl> <chr>
1 bulbasaur 1 64 grass
2 ivysaur 2 142 grass
3 venusaur 3 236 grass
4 charmander 4 62 fire
5 charmeleon 5 142 fire
6 charizard 6 240 fire
7 squirtle 7 63 water
8 wartortle 8 142 water
9 blastoise 9 239 water
10 caterpie 10 39 bug
# ℹ 939 more rows
Otra opción es realizar una selección por rango. Aquí podemos notar que el programa internamente está usando la posición de las columnas para realizar la selección.
# A tibble: 949 × 8
id pokemon species_id height weight base_experience type_1 egg_group_2
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 1 bulbasaur 1 0.7 6.9 64 grass plant
2 2 ivysaur 2 1 13 142 grass plant
3 3 venusaur 3 2 100 236 grass plant
4 4 charmander 4 0.6 8.5 62 fire dragon
5 5 charmeleon 5 1.1 19 142 fire dragon
6 6 charizard 6 1.7 90.5 240 fire dragon
7 7 squirtle 7 0.5 9 63 water water1
8 8 wartortle 8 1 22.5 142 water water1
9 9 blastoise 9 1.6 85.5 239 water water1
10 10 caterpie 10 0.3 2.9 39 bug <NA>
# ℹ 939 more rows
# A tibble: 949 × 8
id pokemon species_id height weight base_experience type_1 generation_id
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass 1
2 2 ivysaur 2 1 13 142 grass 1
3 3 venusaur 3 2 100 236 grass 1
4 4 charmand… 4 0.6 8.5 62 fire 1
5 5 charmele… 5 1.1 19 142 fire 1
6 6 charizard 6 1.7 90.5 240 fire 1
7 7 squirtle 7 0.5 9 63 water 1
8 8 wartortle 8 1 22.5 142 water 1
9 9 blastoise 9 1.6 85.5 239 water 1
10 10 caterpie 10 0.3 2.9 39 bug 1
# ℹ 939 more rows
Para realizar una selección negativa en estos casos se puede anteponer el signo menos -
# A tibble: 949 × 15
type_2 hp attack defense special_attack special_defense speed color_1
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 poison 45 49 49 65 65 45 #78C850
2 poison 60 62 63 80 80 60 #78C850
3 poison 80 82 83 100 100 80 #78C850
4 <NA> 39 52 43 60 50 65 #F08030
5 <NA> 58 64 58 80 65 80 #F08030
6 flying 78 84 78 109 85 100 #F08030
7 <NA> 44 48 65 50 64 43 #6890F0
8 <NA> 59 63 80 65 80 58 #6890F0
9 <NA> 79 83 100 85 105 78 #6890F0
10 <NA> 45 30 35 20 20 45 #A8B820
# ℹ 939 more rows
# ℹ 7 more variables: color_2 <chr>, color_f <chr>, egg_group_1 <chr>,
# egg_group_2 <chr>, url_icon <chr>, generation_id <dbl>, url_image <chr>
# A tibble: 949 × 15
type_2 hp attack defense special_attack special_defense speed color_1
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 poison 45 49 49 65 65 45 #78C850
2 poison 60 62 63 80 80 60 #78C850
3 poison 80 82 83 100 100 80 #78C850
4 <NA> 39 52 43 60 50 65 #F08030
5 <NA> 58 64 58 80 65 80 #F08030
6 flying 78 84 78 109 85 100 #F08030
7 <NA> 44 48 65 50 64 43 #6890F0
8 <NA> 59 63 80 65 80 58 #6890F0
9 <NA> 79 83 100 85 105 78 #6890F0
10 <NA> 45 30 35 20 20 45 #A8B820
# ℹ 939 more rows
# ℹ 7 more variables: color_2 <chr>, color_f <chr>, egg_group_1 <chr>,
# egg_group_2 <chr>, url_icon <chr>, generation_id <dbl>, url_image <chr>
2.2 Usando selection helpers
Tidyverse tiene un paquete llamado tidyselect que trabaja de manera interna y cuenta con algunas funciones que facilitan el proceso de selección de variables (entre otras cosas):
-
everything(): selecciona todas las variables. -
last_col(): selecciona la última variable. -
group_cols(): selecciona las columnas agrupadas. -
starts_with: selecciona las variables con un prefijo especificado. -
ends_with: selecciona las variables con un sufijo especificado. -
contains: selecciona las variables que contienen uno más caracteres especificados. -
matches: seleccion variables por expresiones regulares. Estas son formas de especificarle al programa que encuentre un patrón específico en una cadena de caracteres. -
num_range: selecciona variables con un patrón numérico. Por ejemplo “p01”, “p02”, “p03”, etc.
A continuación se muestran algunos ejemplos aplicando estas funciones:
En este caso, se seleccionan todas las columnas, menos “id” y “url_image”.
# A tibble: 949 × 20
pokemon species_id height weight base_experience type_1 type_2 hp attack
<chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl> <dbl>
1 bulbasaur 1 0.7 6.9 64 grass poison 45 49
2 ivysaur 2 1 13 142 grass poison 60 62
3 venusaur 3 2 100 236 grass poison 80 82
4 charmand… 4 0.6 8.5 62 fire <NA> 39 52
5 charmele… 5 1.1 19 142 fire <NA> 58 64
6 charizard 6 1.7 90.5 240 fire flying 78 84
7 squirtle 7 0.5 9 63 water <NA> 44 48
8 wartortle 8 1 22.5 142 water <NA> 59 63
9 blastoise 9 1.6 85.5 239 water <NA> 79 83
10 caterpie 10 0.3 2.9 39 bug <NA> 45 30
# ℹ 939 more rows
# ℹ 11 more variables: defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>
En el siguiente ejemplo se realiza un doble select(). Primero para eliminar la última columna del conjunto de datos. Luego, se selecciona la columna que corresponde al nombre del pokémon; la última, que en este caso es el identificador de la generación y luego la columna que muestra el tipo del pokémon.
set.seed(1234) # Esta semilla permite replicar la selección aleatoria
data_poke |>
select(-url_image) |>
select(pokemon, last_col(), type_1) |>
slice_sample(n = 10) # Selección aleatoria# A tibble: 10 × 3
pokemon generation_id type_1
<chr> <dbl> <chr>
1 masquerain 3 bug
2 scizor-mega NA bug
3 greninja-battle-bond NA water
4 electrode 1 electric
5 golurk 5 ground
6 vulpix-alola NA ice
7 landorus-incarnate 5 ground
8 minior-green-meteor NA rock
9 bibarel 4 normal
10 pikachu-kalos-cap NA electric
La función set.seed() permite replicar un procedimiento aleatorio, para obtener el mismo resultado con cada ejecución. Es sumamente útil para darle reproducibilidad a un proceso que implique una selección aleatoria.
Para quienes estén interesados sobre números aleatorios en los computadores, pueden revisar este video del canal de YouTube Derivando-
En el siguiente código se seleccionan los identificadores y nombres, pero además se usa la función starts_with() para seleccionar todo lo que comience con “type”.
# A tibble: 949 × 4
id pokemon type_1 type_2
<dbl> <chr> <chr> <chr>
1 1 bulbasaur grass poison
2 2 ivysaur grass poison
3 3 venusaur grass poison
4 4 charmander fire <NA>
5 5 charmeleon fire <NA>
6 6 charizard fire flying
7 7 squirtle water <NA>
8 8 wartortle water <NA>
9 9 blastoise water <NA>
10 10 caterpie bug <NA>
# ℹ 939 more rows
O aquellas que terminen con “ght”, empleando la función ends_with().
# A tibble: 949 × 4
id pokemon height weight
<dbl> <chr> <dbl> <dbl>
1 1 bulbasaur 0.7 6.9
2 2 ivysaur 1 13
3 3 venusaur 2 100
4 4 charmander 0.6 8.5
5 5 charmeleon 1.1 19
6 6 charizard 1.7 90.5
7 7 squirtle 0.5 9
8 8 wartortle 1 22.5
9 9 blastoise 1.6 85.5
10 10 caterpie 0.3 2.9
# ℹ 939 more rows
Por su parte, la función contains() es más amplia, pues seleccionará todas las variables que incluyan el string especificado.
# A tibble: 949 × 16
id pokemon species_id base_experience type_1 type_2 special_attack
<dbl> <chr> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 64 grass poison 65
2 2 ivysaur 2 142 grass poison 80
3 3 venusaur 3 236 grass poison 100
4 4 charmander 4 62 fire <NA> 60
5 5 charmeleon 5 142 fire <NA> 80
6 6 charizard 6 240 fire flying 109
7 7 squirtle 7 63 water <NA> 50
8 8 wartortle 8 142 water <NA> 65
9 9 blastoise 9 239 water <NA> 85
10 10 caterpie 10 39 bug <NA> 20
# ℹ 939 more rows
# ℹ 9 more variables: special_defense <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
Y la función matches() es mucho más potente, pues se le puede especificar cualquier patrón a través de una expresión regular. Por ejemplo, ahora seleccionaremos todas las variables que incluyan solamente letras minúsculas en su nombre.
Esta expresión regular se puede definir del siguiente modo:
-
^: indica el inicio del string. -
[a-z]: indica caracteres desde la “a” a la “z” en minúscula. -
*: indica que deben ser 0 o más repeticiones de esos caracteres. -
$: indica el fin del string.
# A tibble: 949 × 8
id pokemon height weight hp attack defense speed
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 bulbasaur 0.7 6.9 45 49 49 45
2 2 ivysaur 1 13 60 62 63 60
3 3 venusaur 2 100 80 82 83 80
4 4 charmander 0.6 8.5 39 52 43 65
5 5 charmeleon 1.1 19 58 64 58 80
6 6 charizard 1.7 90.5 78 84 78 100
7 7 squirtle 0.5 9 44 48 65 43
8 8 wartortle 1 22.5 59 63 80 58
9 9 blastoise 1.6 85.5 79 83 100 78
10 10 caterpie 0.3 2.9 45 30 35 45
# ℹ 939 more rows
Expresiones regulares no es un contenido que se verá en el curso. Solo se muestra un ejemplo para que conozcan que existe esa opción.
Y en cuanto a la función num_range(), esta es particularmente útil en conjuntos de datos que tienen nombres correlativos usando como prefijo una letra.
# A tibble: 949 × 3
pokemon type_1 type_2
<chr> <chr> <chr>
1 bulbasaur grass poison
2 ivysaur grass poison
3 venusaur grass poison
4 charmander fire <NA>
5 charmeleon fire <NA>
6 charizard fire flying
7 squirtle water <NA>
8 wartortle water <NA>
9 blastoise water <NA>
10 caterpie bug <NA>
# ℹ 939 more rows
2.3 Por variables indicadas en un vector
Otra forma para realizar la selección de variables es a través de un vector que incluya los nombres de cada columna. Existen dos funciones para esta operación:
all_of(): define un vector de caracteres con los nombres de variables. Todos los nombres deben estar en el conjunto de datos o lanzará un error.any_of(): al igual que la función anterior, define un vector de caracteres con los nombres. Sin embargo, no arrojará error si este no existe en el conjunto.
nombres_inicial <- c("id", "pokemon", "nombre_no_existe")
data_poke |> select(any_of(nombres_inicial)) # Si usáramos all_of daría error.# A tibble: 949 × 2
id pokemon
<dbl> <chr>
1 1 bulbasaur
2 2 ivysaur
3 3 venusaur
4 4 charmander
5 5 charmeleon
6 6 charizard
7 7 squirtle
8 8 wartortle
9 9 blastoise
10 10 caterpie
# ℹ 939 more rows
nombres <- names(data_poke) # Función names() entrega nombres de columnas del dataframe
data_poke |> select(any_of(nombres))# A tibble: 949 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass poison 45
2 2 ivysaur 2 1 13 142 grass poison 60
3 3 venusaur 3 2 100 236 grass poison 80
4 4 charmander 4 0.6 8.5 62 fire <NA> 39
5 5 charmeleon 5 1.1 19 142 fire <NA> 58
6 6 charizard 6 1.7 90.5 240 fire flying 78
7 7 squirtle 7 0.5 9 63 water <NA> 44
8 8 wartortle 8 1 22.5 142 water <NA> 59
9 9 blastoise 9 1.6 85.5 239 water <NA> 79
10 10 caterpie 10 0.3 2.9 39 bug <NA> 45
# ℹ 939 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
2.4 Aplicando funciones a variables
Muchas veces podemos estar interesados/as en realizar selecciones según el tipo de variable o aplicando alguna función. En estos casos where() se vuelve muy útil. Este aplica una función a todas las variables y selecciona aquellas cuyo valor de la función sea TRUE.
Por ejemplo, podríamos aplicar funciones para consultar el tipo de dato de la columna. Esta devolverá TRUE en caso de que la columna sea del tipo especificado y FALSE en todos los otros escenarios.
-
is.numeric(): devuelve TRUE si la variable esnumeric. -
is.character(): devuelve TRUE si la variable escharacter. -
is.factor(): devuelve TRUE si la variable esfactor. -
is.logical(): devuelve TRUE si la variable eslogical. -
is.date(): devuelve TRUE si la variable esdate.
El código que se presenta en el siguiente bloque seleccionará todas las variables de tipo numeric.
# A tibble: 949 × 12
id species_id height weight base_experience hp attack defense
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 1 0.7 6.9 64 45 49 49
2 2 2 1 13 142 60 62 63
3 3 3 2 100 236 80 82 83
4 4 4 0.6 8.5 62 39 52 43
5 5 5 1.1 19 142 58 64 58
6 6 6 1.7 90.5 240 78 84 78
7 7 7 0.5 9 63 44 48 65
8 8 8 1 22.5 142 59 63 80
9 9 9 1.6 85.5 239 79 83 100
10 10 10 0.3 2.9 39 45 30 35
# ℹ 939 more rows
# ℹ 4 more variables: special_attack <dbl>, special_defense <dbl>, speed <dbl>,
# generation_id <dbl>
Y este todas las variables de tipo character
# A tibble: 949 × 10
pokemon type_1 type_2 color_1 color_2 color_f egg_group_1 egg_group_2
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 bulbasaur grass poison #78C850 #A040A0 #81A763 monster plant
2 ivysaur grass poison #78C850 #A040A0 #81A763 monster plant
3 venusaur grass poison #78C850 #A040A0 #81A763 monster plant
4 charmander fire <NA> #F08030 <NA> <NA> monster dragon
5 charmeleon fire <NA> #F08030 <NA> <NA> monster dragon
6 charizard fire flying #F08030 #A890F0 #DE835E monster dragon
7 squirtle water <NA> #6890F0 <NA> <NA> monster water1
8 wartortle water <NA> #6890F0 <NA> <NA> monster water1
9 blastoise water <NA> #6890F0 <NA> <NA> monster water1
10 caterpie bug <NA> #A8B820 <NA> <NA> bug <NA>
# ℹ 939 more rows
# ℹ 2 more variables: url_icon <chr>, url_image <chr>
Y de igual forma podríamos aplicar otra función para obtener solo las variables numéricas cuya media aritmética sea superior a 50.
# A tibble: 949 × 10
id species_id weight base_experience hp attack defense special_attack
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 1 6.9 64 45 49 49 65
2 2 2 13 142 60 62 63 80
3 3 3 100 236 80 82 83 100
4 4 4 8.5 62 39 52 43 60
5 5 5 19 142 58 64 58 80
6 6 6 90.5 240 78 84 78 109
7 7 7 9 63 44 48 65 50
8 8 8 22.5 142 59 63 80 65
9 9 9 85.5 239 79 83 100 85
10 10 10 2.9 39 45 30 35 20
# ℹ 939 more rows
# ℹ 2 more variables: special_defense <dbl>, speed <dbl>
Este código puede ser más complejo, por lo que puede resultar útil explicar algunos conceptos:
- En primer lugar, se utiliza
where()para definir una función, la cual es denotada por la virgulilla~. - Esta función evalúa para cada elemento, el cual es denotado genéricamente como
.xsi es que es de tipo numérico. - Además, para cada elemento, evaluará que la media, a la cual se le remueven los casos perdidos, sea superior a 50.
- Para estas operaciones se utiliza el operador
&&en vez de&. Esto se debe a que estamos evaluando que ambas condiciones sean verdaderas, pero para cada columna individualmente. Para más información se puede revisar este link. - Cuando se usa
&&, solo se evalúa la segunda condición cuando la primera es verdadera. Es decir, solo aquellas variables que sean numéricas se les evaluará si su media aritmética es superior a 50. Para quienes cumplan ambos criterios, serán seleccionadas.
3 rename()
Esta función permite renombrar columnas siguiendo la estructura nombre_nuevo = nombre_antiguo. Para ello se pueden usar al menos tres métodos
- Especificar por nombre.
- Usando un vector.
- Usando funciones.
3.1 Por nombre
En su formulación más simple, basta con especificar el nombre nuevo y asignarlo al nombre que anteriormente tenía la variable.
data_poke |>
rename(peso = weight,
altura = height,
primer_tipo = type_1) |>
select(peso, altura, primer_tipo)# A tibble: 949 × 3
peso altura primer_tipo
<dbl> <dbl> <chr>
1 6.9 0.7 grass
2 13 1 grass
3 100 2 grass
4 8.5 0.6 fire
5 19 1.1 fire
6 90.5 1.7 fire
7 9 0.5 water
8 22.5 1 water
9 85.5 1.6 water
10 2.9 0.3 bug
# ℹ 939 more rows
La función select() también entrega la posibilidad de renombrar variables, lo que puede reducir el código presentado anteriormente.
# A tibble: 949 × 3
peso altura primer_tipo
<dbl> <dbl> <chr>
1 6.9 0.7 grass
2 13 1 grass
3 100 2 grass
4 8.5 0.6 fire
5 19 1.1 fire
6 90.5 1.7 fire
7 9 0.5 water
8 22.5 1 water
9 85.5 1.6 water
10 2.9 0.3 bug
# ℹ 939 more rows
3.2 Usando vectores
Es posible definir un vector y aplicar la función all_of() o any_of()revisados anteriormente.
nuevos_nombres <- c(id_pokemon = "id", id_especies = "species_id",
altura = "height", peso = "weight",
exp_base = "base_experience",
tipo_1 = "type_1", tipo_2 = "type_2")
data_poke |>
rename(all_of(nuevos_nombres))# A tibble: 949 × 22
id_pokemon pokemon id_especies altura peso exp_base tipo_1 tipo_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass poison 45
2 2 ivysaur 2 1 13 142 grass poison 60
3 3 venusaur 3 2 100 236 grass poison 80
4 4 charmander 4 0.6 8.5 62 fire <NA> 39
5 5 charmeleon 5 1.1 19 142 fire <NA> 58
6 6 charizard 6 1.7 90.5 240 fire flying 78
7 7 squirtle 7 0.5 9 63 water <NA> 44
8 8 wartortle 8 1 22.5 142 water <NA> 59
9 9 blastoise 9 1.6 85.5 239 water <NA> 79
10 10 caterpie 10 0.3 2.9 39 bug <NA> 45
# ℹ 939 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
3.3 Aplicando funciones
A veces necesitaremos realizar una transformación masiva en los nombres de la base de datos. En ese caso, la mejor opción es usar rename_with() junto a la función indicada.
En el siguiente ejemplo, cambiaremos todos los guiones bajos de los nombres por un punto. Para ello emplearemos la función str_replace() del paquete stringr.
# A tibble: 949 × 22
id pokemon species.id height weight base.experience type.1 type.2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass poison 45
2 2 ivysaur 2 1 13 142 grass poison 60
3 3 venusaur 3 2 100 236 grass poison 80
4 4 charmander 4 0.6 8.5 62 fire <NA> 39
5 5 charmeleon 5 1.1 19 142 fire <NA> 58
6 6 charizard 6 1.7 90.5 240 fire flying 78
7 7 squirtle 7 0.5 9 63 water <NA> 44
8 8 wartortle 8 1 22.5 142 water <NA> 59
9 9 blastoise 9 1.6 85.5 239 water <NA> 79
10 10 caterpie 10 0.3 2.9 39 bug <NA> 45
# ℹ 939 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special.attack <dbl>,
# special.defense <dbl>, speed <dbl>, color.1 <chr>, color.2 <chr>,
# color.f <chr>, egg.group_1 <chr>, egg.group_2 <chr>, url.icon <chr>,
# generation.id <dbl>, url.image <chr>
4 relocate
Esta función simplemente cambia la posición de las columnas, para lo cual se le indican los nombres de las columnas que desea. Adicionalmente cuenta con los argumentos .after y .before para indicar después o antes de qué columna irán las especificadas.
# A tibble: 949 × 22
id pokemon generation_id species_id height weight base_experience type_1
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 bulbasaur 1 1 0.7 6.9 64 grass
2 2 ivysaur 1 2 1 13 142 grass
3 3 venusaur 1 3 2 100 236 grass
4 4 charmand… 1 4 0.6 8.5 62 fire
5 5 charmele… 1 5 1.1 19 142 fire
6 6 charizard 1 6 1.7 90.5 240 fire
7 7 squirtle 1 7 0.5 9 63 water
8 8 wartortle 1 8 1 22.5 142 water
9 9 blastoise 1 9 1.6 85.5 239 water
10 10 caterpie 1 10 0.3 2.9 39 bug
# ℹ 939 more rows
# ℹ 14 more variables: type_2 <chr>, hp <dbl>, attack <dbl>, defense <dbl>,
# special_attack <dbl>, special_defense <dbl>, speed <dbl>, color_1 <chr>,
# color_2 <chr>, color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>,
# url_icon <chr>, url_image <chr>
# A tibble: 949 × 22
id generation_id pokemon species_id height weight base_experience type_1
<dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 1 bulbasaur 1 0.7 6.9 64 grass
2 2 1 ivysaur 2 1 13 142 grass
3 3 1 venusaur 3 2 100 236 grass
4 4 1 charmand… 4 0.6 8.5 62 fire
5 5 1 charmele… 5 1.1 19 142 fire
6 6 1 charizard 6 1.7 90.5 240 fire
7 7 1 squirtle 7 0.5 9 63 water
8 8 1 wartortle 8 1 22.5 142 water
9 9 1 blastoise 9 1.6 85.5 239 water
10 10 1 caterpie 10 0.3 2.9 39 bug
# ℹ 939 more rows
# ℹ 14 more variables: type_2 <chr>, hp <dbl>, attack <dbl>, defense <dbl>,
# special_attack <dbl>, special_defense <dbl>, speed <dbl>, color_1 <chr>,
# color_2 <chr>, color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>,
# url_icon <chr>, url_image <chr>
Y de igual forma, se pueden usar las funciones de tidyselect.
# A tibble: 949 × 22
id pokemon species_id height weight base_experience generation_id type_1
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 bulbasaur 1 0.7 6.9 64 1 grass
2 2 ivysaur 2 1 13 142 1 grass
3 3 venusaur 3 2 100 236 1 grass
4 4 charmand… 4 0.6 8.5 62 1 fire
5 5 charmele… 5 1.1 19 142 1 fire
6 6 charizard 6 1.7 90.5 240 1 fire
7 7 squirtle 7 0.5 9 63 1 water
8 8 wartortle 8 1 22.5 142 1 water
9 9 blastoise 9 1.6 85.5 239 1 water
10 10 caterpie 10 0.3 2.9 39 1 bug
# ℹ 939 more rows
# ℹ 14 more variables: type_2 <chr>, hp <dbl>, attack <dbl>, defense <dbl>,
# special_attack <dbl>, special_defense <dbl>, speed <dbl>, color_1 <chr>,
# color_2 <chr>, color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>,
# url_icon <chr>, url_image <chr>
5 filter
Permite obtener un subconjunto de observaciones a partir de las condiciones lógicas especificadas.Estas condiciones lógicas están definidas por el lenguaje de programación.
Cabe mencionar que es imperativo manejar estas condiciones, pues se utilizan en múltiples etapas del procesamiento y análisis de datos.
| Símbolo | Definición |
|---|---|
| == | Igualdad. No debe confundirse con “=”, que es un operador de asignación |
| != | Distinto |
| ! | Negación de una expresión lógica |
| > | Mayor que |
| < | Menor que |
| >= | Mayor o igual que |
| <= | Menor o igual que |
| %in% | Operador de R que indica un conjunto de elementos |
| & | Operador “y”. Todas las condiciones evaluadas deben ser verdaderas para que la expresión lo sea |
| | | Operador “o”. Al menos una condición debe ser verdadera para que la expresión lo sea |
En los siguientes códigos se muestran una serie de ejemplos de aplicaciones de filtros.
# Respetar mayúsculas y minúsculas
# Selecciona todos los type_1 fuego
data_poke |>
filter(type_1 == "fire")# A tibble: 59 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 4 charmander 4 0.6 8.5 62 fire <NA> 39
2 5 charmeleon 5 1.1 19 142 fire <NA> 58
3 6 charizard 6 1.7 90.5 240 fire flying 78
4 37 vulpix 37 0.6 9.9 60 fire <NA> 38
5 38 ninetales 38 1.1 19.9 177 fire <NA> 73
6 58 growlithe 58 0.7 19 70 fire <NA> 55
7 59 arcanine 59 1.9 155 194 fire <NA> 90
8 77 ponyta 77 1 30 82 fire <NA> 50
9 78 rapidash 78 1.7 95 175 fire <NA> 65
10 126 magmar 126 1.3 44.5 173 fire <NA> 65
# ℹ 49 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 890 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass poison 45
2 2 ivysaur 2 1 13 142 grass poison 60
3 3 venusaur 3 2 100 236 grass poison 80
4 7 squirtle 7 0.5 9 63 water <NA> 44
5 8 wartortle 8 1 22.5 142 water <NA> 59
6 9 blastoise 9 1.6 85.5 239 water <NA> 79
7 10 caterpie 10 0.3 2.9 39 bug <NA> 45
8 11 metapod 11 0.7 9.9 72 bug <NA> 50
9 12 butterfree 12 1.1 32 178 bug flying 60
10 13 weedle 13 0.3 3.2 39 bug poison 40
# ℹ 880 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# Selecciona cualquiera que sea ghost o steel en type_1
data_poke |>
filter(type_1 %in% c("ghost", "steel"))# A tibble: 70 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 92 gastly 92 1.3 0.1 62 ghost poison 30
2 93 haunter 93 1.6 0.1 142 ghost poison 45
3 94 gengar 94 1.5 40.5 225 ghost poison 60
4 200 misdreavus 200 0.7 1 87 ghost <NA> 60
5 208 steelix 208 9.2 400 179 steel ground 75
6 227 skarmory 227 1.7 50.5 163 steel flying 65
7 303 mawile 303 0.6 11.5 133 steel fairy 50
8 304 aron 304 0.4 60 66 steel rock 50
9 305 lairon 305 0.9 120 151 steel rock 60
10 306 aggron 306 2.1 360 239 steel rock 70
# ℹ 60 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# Selecciona cualquiera que no sea agua, hierba o fuego en type_1
data_poke |>
filter(!(type_1 %in% c("grass", "fire", "water")))# A tibble: 680 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 10 caterpie 10 0.3 2.9 39 bug <NA> 45
2 11 metapod 11 0.7 9.9 72 bug <NA> 50
3 12 butterfree 12 1.1 32 178 bug flying 60
4 13 weedle 13 0.3 3.2 39 bug poison 40
5 14 kakuna 14 0.6 10 72 bug poison 45
6 15 beedrill 15 1 29.5 178 bug poison 65
7 16 pidgey 16 0.3 1.8 50 normal flying 40
8 17 pidgeotto 17 1.1 30 122 normal flying 63
9 18 pidgeot 18 1.5 39.5 216 normal flying 83
10 19 rattata 19 0.3 3.5 51 normal <NA> 30
# ℹ 670 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# Selecciona tipo hierba en type_1 de segunda generación
data_poke |>
filter(type_1 == "grass" & generation_id == 2) # A tibble: 9 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 152 chikorita 152 0.9 6.4 64 grass <NA> 45
2 153 bayleef 153 1.2 15.8 142 grass <NA> 60
3 154 meganium 154 1.8 100. 236 grass <NA> 80
4 182 bellossom 182 0.4 5.8 221 grass <NA> 75
5 187 hoppip 187 0.4 0.5 50 grass flying 35
6 188 skiploom 188 0.6 1 119 grass flying 55
7 189 jumpluff 189 0.8 3 207 grass flying 75
8 191 sunkern 191 0.3 1.8 36 grass <NA> 30
9 192 sunflora 192 0.8 8.5 149 grass <NA> 75
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 44 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 87 dewgong 87 1.7 120 166 water ice 90
2 91 cloyster 91 1.5 132. 184 water ice 50
3 124 jynx 124 1.4 40.6 159 ice psychic 65
4 131 lapras 131 2.5 220 187 water ice 130
5 144 articuno 144 1.7 55.4 261 ice flying 90
6 215 sneasel 215 0.9 28 86 dark ice 55
7 220 swinub 220 0.4 6.5 50 ice ground 50
8 221 piloswine 221 1.1 55.8 158 ice ground 100
9 225 delibird 225 0.9 16 116 ice flying 45
10 238 smoochum 238 0.4 6 61 ice psychic 45
# ℹ 34 more rows
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
Con las funciones de stringr se pueden realizar filtros más específicos para variables de tipo character. Por ejemplo, en el siguiente filtro se seleccionan todas los pokémon cuyo nombre finalice en chu.
# A tibble: 3 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 25 pikachu 25 0.4 6 112 electric <NA> 35
2 26 raichu 26 0.8 30 218 electric <NA> 60
3 172 pichu 172 0.3 2 41 electric <NA> 20
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
6 arrange
Es una función que ermite ordenar las filas a partir de valores de las columnas. Por defecto lo realizará de manera ascendente.
# A tibble: 949 × 2
pokemon attack
<chr> <dbl>
1 chansey 5
2 happiny 5
3 magikarp 10
4 shuckle 10
5 blissey 10
6 feebas 15
7 metapod 20
8 abra 20
9 ledyba 20
10 togepi 20
# ℹ 939 more rows
# Por tipo y luego descendente por ataque
data_poke |>
arrange(type_1, desc(attack)) |>
select(pokemon, type_1, attack)# A tibble: 949 × 3
pokemon type_1 attack
<chr> <chr> <dbl>
1 heracross-mega bug 185
2 pinsir-mega bug 155
3 scizor-mega bug 150
4 beedrill-mega bug 150
5 buzzwole bug 139
6 pheromosa bug 137
7 escavalier bug 135
8 scizor bug 130
9 pinsir bug 125
10 heracross bug 125
# ℹ 939 more rows
7 slice
Posibilita seleccionar filas a partir de su posición. Esta selección se puede realizar
- A partir de valores únicos o rangos utilizando dos puntos
:. - Excluyendo posiciones o rango de posiciones empleando el símbolo menos
-. - Seleccionar observaciones desde el principio o final con
slice_head()yslice_tail(), respectivamente. - Seleccionar muestras aleatorias de casos, ya sea a partir de números o porcentajes, con los argumentos
nypropsegún corresponda.
# A tibble: 1 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 150 mewtwo 150 2 122 306 psychic <NA> 106
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 5 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 236 tyrogue 236 0.7 21 42 fighting <NA> 35
2 237 hitmontop 237 1.4 48 159 fighting <NA> 50
3 238 smoochum 238 0.4 6 61 ice psych… 45
4 239 elekid 239 0.6 23.5 72 electric <NA> 45
5 240 magby 240 0.7 21.4 73 fire <NA> 45
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 5 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 1 bulbasaur 1 0.7 6.9 64 grass poison 45
2 2 ivysaur 2 1 13 142 grass poison 60
3 3 venusaur 3 2 100 236 grass poison 80
4 4 charmander 4 0.6 8.5 62 fire <NA> 39
5 5 charmeleon 5 1.1 19 142 fire <NA> 58
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 5 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 10143 mimikyu-bu… 778 0.2 0.7 167 ghost fairy 55
2 10144 mimikyu-to… 778 0.4 2.8 167 ghost fairy 55
3 10145 mimikyu-to… 778 0.4 2.8 167 ghost fairy 55
4 10146 kommo-o-to… 784 2.4 208. 270 dragon fight… 75
5 10147 magearna-o… 801 1 80.5 120 steel fairy 80
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>
# A tibble: 7 × 22
id pokemon species_id height weight base_experience type_1 type_2 hp
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1 284 masquerain 284 0.8 3.6 159 bug flying 70
2 10046 scizor-mega 212 2 125 210 bug steel 70
3 10116 greninja-b… 658 1.5 40 239 water dark 72
4 101 electrode 101 1.2 66.6 172 elect… <NA> 60
5 623 golurk 623 2.8 330 169 ground ghost 89
6 10103 vulpix-alo… 37 0.6 9.9 60 ice <NA> 38
7 645 landorus-i… 645 1.5 68 270 ground flying 89
# ℹ 13 more variables: attack <dbl>, defense <dbl>, special_attack <dbl>,
# special_defense <dbl>, speed <dbl>, color_1 <chr>, color_2 <chr>,
# color_f <chr>, egg_group_1 <chr>, egg_group_2 <chr>, url_icon <chr>,
# generation_id <dbl>, url_image <chr>